home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1999 / MacHack 1999.toast / The Hacks / OutOfContextMenus / Source / CPongGameBehavior.cp < prev    next >
Encoding:
Text File  |  1999-06-25  |  7.6 KB  |  274 lines  |  [TEXT/CWIE]

  1. // ===========================================================================
  2. //    CPongGameBehavior.cp                 ©1999 Eric Traut
  3. // ===========================================================================
  4.  
  5. #include "CPongGameBehavior.h"
  6. #include "CShadowWindow.h"
  7.  
  8.  
  9. PicHandle                CPongGameBehavior::sLeftPaddlePICT        = NULL;
  10. PicHandle                CPongGameBehavior::sRightPaddlePICT        = NULL;
  11. CIconHandle                CPongGameBehavior::sBallIcon            = NULL;
  12. SndChannelPtr            CPongGameBehavior::sSoundChannel        = NULL;
  13. SndListHandle            CPongGameBehavior::sBootBeepSound        = NULL;
  14. SndListHandle            CPongGameBehavior::sBootCrashSound        = NULL;
  15.  
  16.  
  17. // ---------------------------------------------------------------------------
  18. //        • CPongGameBehavior
  19. // ---------------------------------------------------------------------------
  20.  
  21. CPongGameBehavior::CPongGameBehavior(
  22.     CShadowWindow &        inShadowWindow)
  23.     :    COffscreenBehavior(inShadowWindow, true, true)
  24. {
  25.     mCurGameState = kPongGameStartState;
  26. }
  27.  
  28.  
  29. // ---------------------------------------------------------------------------
  30. //        • GetTicksForState
  31. // ---------------------------------------------------------------------------
  32.  
  33. void
  34. CPongGameBehavior::DoIdleTask(
  35.     Boolean     inGNETime)
  36. {
  37.     if (inGNETime && mCurGameState == kPongGameStateTearDown)
  38.     {
  39.         // Detach ourselves
  40.         mShadowWindow.DetachBehavior();
  41.     }
  42.     else
  43.     {
  44.         COffscreenBehavior::DoIdleTask(inGNETime);
  45.     }
  46. }
  47.  
  48.  
  49. // ---------------------------------------------------------------------------
  50. //        • RenderToGWorld
  51. // ---------------------------------------------------------------------------
  52.  
  53. Boolean
  54. CPongGameBehavior::RenderToGWorld(
  55.     StGWorldLocker &        inBackingLocker,
  56.     StGWorldLocker &        inRenderingLocker)
  57. {
  58.     #pragma unused (inBackingLocker, inRenderingLocker)
  59.  
  60.     // Start by copying the entire window (so we get the scroll bars, etc.)
  61.     (void) COffscreenBehavior::RenderToGWorld(inBackingLocker, inRenderingLocker);
  62.     
  63.     UInt32        curTicks = ::TickCount();
  64.     Rect        windowContentRect;
  65.     Rect        leftPaddleRect;
  66.     Rect        rightPaddleRect;
  67.     Rect        ballRect;
  68.     Rect        dummyRect;
  69.  
  70.     windowContentRect.top = mGWorldRect.top + 21;
  71.     windowContentRect.bottom = mGWorldRect.bottom - 15;
  72.     windowContentRect.left = mGWorldRect.left;
  73.     windowContentRect.right = mGWorldRect.right - 15;
  74.     
  75.     ThrowIfNULL_(sLeftPaddlePICT);
  76.     ThrowIfNULL_(sRightPaddlePICT);
  77.     ThrowIfNULL_(sBallIcon);
  78.     ThrowIfNULL_(sBootBeepSound);
  79.     ThrowIfNULL_(sBootCrashSound);
  80.     ThrowIfNULL_(sSoundChannel);
  81.  
  82.     // Erase the old background of the scrolling content area
  83.     ::BackColor(whiteColor);
  84.     ::EraseRect(&windowContentRect);
  85.  
  86.     switch (mCurGameState)
  87.     {
  88.         case kPongGameStartState:
  89.             // Set up the initial state of the game
  90.             mBallLoc.h = (windowContentRect.left + windowContentRect.right) / 2;
  91.             mBallLoc.v = (windowContentRect.top + windowContentRect.bottom) / 2;
  92.             mBallVector.h = -3;
  93.             mBallVector.v = -1;
  94.             mColliding = false;
  95.  
  96.             mLeftPaddleVDelta = 0;
  97.             mRightPaddleVDelta = 0;
  98.  
  99.             mLeftPaddleVHeight = 0;
  100.             mRightPaddleVHeight = 0;
  101.             
  102.             mCurGameState = kPongGameStatePlaying;
  103.             break;
  104.             
  105.         case kPongGameStatePlaying:
  106.             leftPaddleRect.left = 7;
  107.             leftPaddleRect.top = mLeftPaddleVHeight + 21;
  108.             leftPaddleRect.right = leftPaddleRect.left + sLeftPaddlePICT[0]->picFrame.right - sLeftPaddlePICT[0]->picFrame.left;
  109.             leftPaddleRect.bottom = leftPaddleRect.top + sLeftPaddlePICT[0]->picFrame.bottom - sLeftPaddlePICT[0]->picFrame.top;
  110.  
  111.             rightPaddleRect.right = windowContentRect.right - 8;
  112.             rightPaddleRect.top = mRightPaddleVHeight + 23;
  113.             rightPaddleRect.left = rightPaddleRect.right - sRightPaddlePICT[0]->picFrame.right + sRightPaddlePICT[0]->picFrame.left;
  114.             rightPaddleRect.bottom = rightPaddleRect.top + sRightPaddlePICT[0]->picFrame.bottom - sRightPaddlePICT[0]->picFrame.top;
  115.             
  116.             // Draw the two paddles
  117.             ::DrawPicture(sLeftPaddlePICT, &leftPaddleRect);
  118.             ::DrawPicture(sRightPaddlePICT, &rightPaddleRect);
  119.  
  120.             // Draw the ball
  121.             ballRect.top = mBallLoc.v - 8;
  122.             ballRect.bottom = mBallLoc.v + 8;
  123.             ballRect.left = mBallLoc.h - 8;
  124.             ballRect.right = mBallLoc.h + 8;
  125.             ::PlotCIcon(&ballRect, sBallIcon);
  126.  
  127.             if (mLastUpdateTicks != curTicks)
  128.             {
  129.                 // Update the paddle location
  130.                 mLeftPaddleVHeight += mLeftPaddleVDelta;
  131.                 mRightPaddleVHeight += mRightPaddleVDelta;
  132.                 
  133.                 if (mLeftPaddleVHeight < 0)
  134.                     mLeftPaddleVHeight = 0;
  135.                 else if (mLeftPaddleVHeight > windowContentRect.bottom - (sLeftPaddlePICT[0]->picFrame.bottom - sLeftPaddlePICT[0]->picFrame.top) - 24)
  136.                     mLeftPaddleVHeight = windowContentRect.bottom - (sLeftPaddlePICT[0]->picFrame.bottom - sLeftPaddlePICT[0]->picFrame.top) - 24;
  137.                 if (mRightPaddleVHeight < 0)
  138.                     mRightPaddleVHeight = 0;
  139.                 else if (mRightPaddleVHeight > windowContentRect.bottom - (sRightPaddlePICT[0]->picFrame.bottom - sRightPaddlePICT[0]->picFrame.top) - 24)
  140.                     mRightPaddleVHeight = windowContentRect.bottom - (sRightPaddlePICT[0]->picFrame.bottom - sRightPaddlePICT[0]->picFrame.top) - 24;
  141.                 
  142.                 mLeftPaddleVDelta = 0;
  143.                 mRightPaddleVDelta = 0;
  144.                 
  145.                 // Update the ball location
  146.                 mBallLoc.h += mBallVector.h;
  147.                 mBallLoc.v += mBallVector.v;
  148.                 
  149.                 // Check for game-over conditions
  150.                 if (mBallLoc.h < 8 ||
  151.                     mBallLoc.h > windowContentRect.right - 8)
  152.                 {
  153.                     (void) ::SndPlay(sSoundChannel, sBootCrashSound, true);
  154.                     mCurGameState = kPongGameStateTearDown;
  155.                 }
  156.                 // Check for top/bottom collisions
  157.                 if (mBallLoc.v < 21 + 8 ||
  158.                     mBallLoc.v > windowContentRect.bottom - 8)
  159.                 {
  160.                     mBallVector.v = -mBallVector.v;
  161.                 }
  162.                 // Check for paddle collisions
  163.                 else if (::SectRect(&ballRect, &leftPaddleRect, &dummyRect) ||
  164.                         ::SectRect(&ballRect, &rightPaddleRect, &dummyRect))
  165.                 {
  166.                     if (!mColliding)
  167.                     {
  168.                         SInt32        newHSpeed = (::Random() + 0x7FFF) % 5;
  169.                         if (newHSpeed <= 1)
  170.                             newHSpeed = 3;
  171.  
  172.                         SInt32        newVSpeed = ::Random() % 3;
  173.                         
  174.                         (void) ::SndPlay(sSoundChannel, sBootBeepSound, true);
  175.                         if (mBallVector.h > 0)
  176.                             mBallVector.h = -newHSpeed;
  177.                         else
  178.                             mBallVector.h = newHSpeed;
  179.  
  180.                         mBallVector.v = newVSpeed;
  181.                         mColliding = true;
  182.                     }
  183.                 }
  184.                 else
  185.                 {
  186.                     mColliding = false;
  187.                 }
  188.                 
  189.                 mLastUpdateTicks = curTicks;
  190.             }
  191.             break;
  192.         
  193.         case kPongGameStateTearDown:
  194.             
  195.             break;
  196.     }
  197.  
  198.     return true;
  199. }
  200.  
  201.  
  202. // ---------------------------------------------------------------------------
  203. //        • Initialize                                        [static]
  204. // ---------------------------------------------------------------------------
  205.  
  206. void
  207. CPongGameBehavior::Initialize(
  208.     SndChannelPtr        inSoundChannel)
  209. {
  210.     sLeftPaddlePICT            = ::GetPicture(131);
  211.     Assert_(sLeftPaddlePICT != NULL);
  212.     
  213.     sRightPaddlePICT        = ::GetPicture(132);
  214.     Assert_(sRightPaddlePICT != NULL);
  215.  
  216.     sBallIcon = ::GetCIcon(128);
  217.     Assert_(sBallIcon != NULL);
  218.  
  219.     sSoundChannel = inSoundChannel;
  220.  
  221.     sBootBeepSound            = reinterpret_cast<SndListHandle>(::Get1Resource('snd ', 130));
  222.     Assert_(sBootBeepSound != NULL);
  223.  
  224.     sBootCrashSound            = reinterpret_cast<SndListHandle>(::Get1Resource('snd ', 129));
  225.     Assert_(sBootCrashSound != NULL);
  226. }
  227.  
  228.  
  229. // ---------------------------------------------------------------------------
  230. //        • HandleEvent
  231. // ---------------------------------------------------------------------------
  232.  
  233. void
  234. CPongGameBehavior::HandleEvent(
  235.     EventRecord *        ioEvent, 
  236.     Boolean *            ioResult)
  237. {
  238.     if (ioEvent->what == keyDown ||
  239.         ioEvent->what == autoKey)
  240.     {
  241.         if ((ioEvent->modifiers & cmdKey) == 0)
  242.         {
  243.             // Swallow any key events
  244.             *ioResult = false;
  245.             
  246.             UInt8        character = ioEvent->message & charCodeMask;
  247.             if (character >= 'a' && character <= 'z')
  248.                 character += 'A' - 'a';
  249.             
  250.             switch (character)
  251.             {
  252.                 case 'W':
  253.                     mLeftPaddleVDelta -= 5;
  254.                     break;
  255.  
  256.                 case 'S':
  257.                     mLeftPaddleVDelta += 5;
  258.                     break;
  259.  
  260.                 case 'I':
  261.                     mRightPaddleVDelta -= 5;
  262.                     break;
  263.  
  264.                 case 'K':
  265.                     mRightPaddleVDelta += 5;
  266.                     break;
  267.             }
  268.         }
  269.     }
  270. }
  271.  
  272.  
  273.     
  274.